﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DevExpress.XtraBars;
using CTEM.Models;
using CTEM.Controllers.BUS;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Views.Base;
using CTEM.Controllers.Global;
using DevExpress.XtraEditors.DXErrorProvider;
using DevExpress.XtraEditors;
using CTEM.Controllers.Global;
using DevExpress.XtraEditors.Controls;
using DevExpress.Utils;
using System.Globalization;
using DevExpress.XtraGrid.Views.Grid;

namespace CTEM.ModuleForms.ManageConstruction
{
    public partial class EstimateManagement : DevExpress.XtraBars.Ribbon.RibbonForm
    {
        private readonly ConstructionBUS _consBUS = new ConstructionBUS();
        private List<CS_EstimateExpensesDTO> _listEsts = new List<CS_EstimateExpensesDTO>();
        private readonly List<CS_EstimateExpensesDTO> _listHistory = new List<CS_EstimateExpensesDTO>();
        private bool _isNew;
        private bool _isAllowEdit;
        public EstimateManagement()
        {
            InitializeComponent();
        }

        private void EstimateManagement_Load(object sender, EventArgs e)
        {
            _isAllowEdit = true;
            AllowEditorNot();
            LoadRepositoryItems();
            LoadActiveEstimate();
        }

        private void barButtonItemLoadAll_ItemClick(object sender, ItemClickEventArgs e)
        {
            LoadRepositoryItems();
            LoadAllEstimate();
        }

        private void barButtonItemRefresh_ItemClick(object sender, ItemClickEventArgs e)
        {
            LoadRepositoryItems();
            LoadActiveEstimate();
        }

        private void barButtonItemUndo_ItemClick(object sender, ItemClickEventArgs e)
        {
            Undo();
        }

        private void barButtonItemRedo_ItemClick(object sender, ItemClickEventArgs e)
        {
            Redo();
        }

        /// <summary>
        /// Allow User can edit or not
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void barButtonItemAllowEdit_ItemClick(object sender, ItemClickEventArgs e)
        {
            AllowEditorNot();
        }

        /// <summary>
        /// Make ExceptionMode is NoAction that's to custom control action when exception thew
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridViewEstimate_InvalidRowException(object sender, InvalidRowExceptionEventArgs e)
        {
            e.ExceptionMode = ExceptionMode.NoAction;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void gridViewEstimate_InvalidValueException(object sender, InvalidValueExceptionEventArgs e)
        {
            e.ErrorText = Constants.INVALIDATE_VALUE;
            e.ExceptionMode = ExceptionMode.DisplayError;
        }

        /// <summary>
        /// Using to edit a estimate
        /// </summary>
        /// <param name="sender">ColumhView</param>
        /// <param name="e">CellValue changed event argurements</param>
        private void gridViewEstimate_CellValueChanged(object sender, CellValueChangedEventArgs e)
        {
            if (!_isNew)
            {
                ColumnView view = sender as ColumnView;
                int currentRow = e.RowHandle;
                CS_EstimateExpensesDTO estDTO = gridViewEstimate.GetRow(currentRow) as CS_EstimateExpensesDTO;
                CS_EstimateExpensesDTO backupEst = _consBUS.GetEstimateExpensesByID(estDTO.ConstructionID);
                bool success = _consBUS.UpdateEstimateExpenses(estDTO);
                if (!success)
                {
                    alertControlMain.Show(this, Constants.ALERT_ERROR, Constants.UPDATE_FAIL);
                }
                else
                {
                    alertControlMain.Show(this, Constants.CONFIRM, "Bạn Đã Cập Nhật Thông Tin Thành Công!");
                    RemoveRedoHistory();
                    backupEst.History = HistoryLevel.EDIT;
                    _listHistory.Add(backupEst);
                }
                _isNew = false;
                LoadActiveEstimate();
            }
        }

        /// <summary>
        /// Allow User Edit Data
        /// </summary>
        private void AllowEditorNot()
        {
            if (_isAllowEdit)
            {
                alertControlMain.Show(this, Constants.CONFIRM, Constants.DISABLE_EIT_MESSAGE);
                _isAllowEdit = false;
                gridViewEstimate.OptionsBehavior.Editable = false;
                barButtonItemAllowEdit.Caption = Constants.ALLOW_EIT;
            }
            else
            {
                DialogResult result = XtraMessageBox.Show(Constants.ALLOW_EIT_MESSAGE, Constants.CONFIRM, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
                if (result == DialogResult.Yes)
                {
                    _isAllowEdit = true;
                    gridViewEstimate.OptionsBehavior.Editable = true;
                    barButtonItemAllowEdit.Caption = Constants.DISABLE_EIT;
                }
            }
        }

        /// <summary>
        /// Load Data for Reporsity Items
        /// </summary>
        private void LoadRepositoryItems()
        {
            ConstructionBUS consBUS = new ConstructionBUS();
            cSConstructionDTOBindingSource.DataSource = consBUS.LoadConstruction(false);
        }

        /// <summary>
        /// Load active Estimates
        /// </summary>
        private void LoadActiveEstimate()
        {
            LoadEstimate(true);
        }

        /// <summary>
        /// Load both active and inactive estimates
        /// </summary>
        private void LoadAllEstimate()
        {
            LoadEstimate(false);
        }

        /// <summary>
        /// Function is called to load constructions
        /// </summary>
        /// <param name="isactive">Load all construction or just active construction</param>
        private void LoadEstimate(bool isactive)
        {
            _listEsts = _consBUS.LoadEstimateEspenses(isactive);
            cSEstimateExpensesDTOBindingSource.DataSource = _listEsts;
        }

        /// <summary>
        /// After undo, item will change status to waiting for redo.
        /// But after new action work, all items wating for redo must be remove
        /// </summary>
        private void RemoveRedoHistory()
        {
            for (int i = 0; i < _listHistory.Count; i++)
            {
                var cons = _listHistory[i];
                if (cons.History.ToString().Contains(Constants.UNDO))
                {
                    _listHistory.Remove(cons);
                    i--;
                }
            }
        }

        /// <summary>
        /// Undo user action
        /// </summary>
        private void Undo()
        {
            int numHistoryItems = _listHistory.Count;
            for (int i = numHistoryItems; i > 0; i--)
            {
                var undoItem = _listHistory[i - 1];
                switch (undoItem.History)
                {
                    case HistoryLevel.ADD:
                        break;
                    case HistoryLevel.EDIT:
                        _listHistory[i - 1] = _consBUS.GetEstimateExpensesByID(undoItem.ConstructionID);
                        _listHistory[i - 1].History = HistoryLevel.UNDO_EDIT;
                        _consBUS.UpdateEstimateExpenses(undoItem);
                        LoadActiveEstimate();
                        return;
                    case HistoryLevel.DELETE:
                        break;
                    case HistoryLevel.UNDO_ADD:
                        break;
                    case HistoryLevel.UNDO_EDIT:
                        break;
                    case HistoryLevel.UNDO_DELETE:
                        break;
                }
            }
        }

        /// <summary>
        /// Redo user action
        /// </summary>
        private void Redo()
        {
            int numHistoryItems = _listHistory.Count;
            for (int i = 0; i < numHistoryItems; i++)
            {
                var redoItem = _listHistory[i];
                switch (redoItem.History)
                {
                    case HistoryLevel.ADD:
                        break;
                    case HistoryLevel.EDIT:
                        break;
                    case HistoryLevel.DELETE:
                        break; ;
                    case HistoryLevel.UNDO_ADD:
                        break;
                    case HistoryLevel.UNDO_EDIT:
                        _listHistory[i] = _consBUS.GetEstimateExpensesByID(redoItem.ConstructionID);
                        _listHistory[i].History = HistoryLevel.EDIT;
                        _consBUS.UpdateEstimateExpenses(redoItem);
                        LoadActiveEstimate();
                        return;
                    case HistoryLevel.UNDO_DELETE:
                        break;
                }
            }
        }

        private void repositoryItemButtonEditEstimateDetail_Click(object sender, EventArgs e)
        {
            int rowIndex = gridViewEstimate.FocusedRowHandle;
            var estimate = gridViewEstimate.GetRow(rowIndex) as CS_EstimateExpensesDTO;
            using (var estimatedetailmanagement = new EstimateDetailManagement(estimate.EstimateExpensesID))
            {
                estimatedetailmanagement.ShowDialog();
            }
            barButtonItemRefresh_ItemClick(null, null);
        }

        private void gridViewEstimate_FocusedRowChanged(object sender, FocusedRowChangedEventArgs e)
        {
            if (e.FocusedRowHandle == GridControl.NewItemRowHandle)
            {
                gridViewEstimate.OptionsBehavior.ReadOnly = false;
            }
            else
            {
                if (_isAllowEdit)
                {
                    barButtonItemAllowEdit_ItemClick(null, null);
                }
            }
        }
    }
}